package cn.zcj.studytest.aspect;


import cn.zcj.studytest.anno.IgnoreLoginUser;
import cn.zcj.studytest.config.ZcjException;
import cn.zcj.studytest.constant.AuthConstant;
import cn.zcj.studytest.domain.SignUp;
import cn.zcj.studytest.service.SignUpService;
import cn.zcj.studytest.utils.JwtUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.IntStream;

@Slf4j
@Aspect
@AllArgsConstructor
@Configuration
public class LoginUserIdAspect {

    @Resource
    private SignUpService signUpService;


    @Around("@annotation(cn.zcj.studytest.anno.LoginUser)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String token = request.getHeader("Token");
        if (StringUtils.isBlank(token)) {
            throw new ZcjException("非法访问");
        }
        Long userId = JwtUtil.checkToken(token);
        if (Objects.isNull(userId)) {
            return joinPoint.proceed();
        }
        SignUp signUp = signUpService.getById(userId);
        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 获取方法
        Method method = methodSignature.getMethod();
        Object[] args = joinPoint.getArgs();
        Parameter[] parameters = method.getParameters();
        // 获取方法的所有参数类型
        IntStream.rangeClosed(0, parameters.length - 1).forEach(i -> {
            Parameter parameter = parameters[i];
            if ("loginUserId".equals(parameter.getName()) && Long.class.equals(parameter.getType())) {
                if (Arrays.stream(parameter.getAnnotations()).anyMatch(e -> IgnoreLoginUser.class.equals(e.annotationType()))) {
                    return;
                }
                args[i] = signUp.getId();
            }
            if (SignUp.class.equals(parameter.getType())) {
                args[i] = signUp;
            }
        });
        return joinPoint.proceed(args);
    }
}
